/** \file gu_render_context.h */
#pragma once

#include "gu_dialect.h"

#include<gr_env_types.h>
#include<list>
#include<string>
#include<functional>

namespace gu {
namespace state {

    /** Actual scene graph should be implemented in a higher level language
 *  This level should contain only minimum amount of complexity and resource
 *  management as needed.
 * */
/** action : data */


    /** Call type  */
enum Setting
{
    /* Store state setters first so sorting and applying is sufficient for storing
     * complete state. */
    SET_CLEAR_COLOR,              // set clear col
    SET_CLEAR_DEPTH,              // set depth

    ENABLE_COLOR_WRITE,
    ENABLE_DEPTH_WRITE,
    ENABLE_DEPTH_TEST,

    DISABLE_COLOR_WRITE,
    DISABLE_DEPTH_WRITE,
    DISABLE_DEPTH_TEST,

    CLEAR_COLOR_BUFFER,
    CLEAR_DEPTH_BUFFER
};

/** Call data */
struct Data
{
    Setting type;
    union{
       gr::Float4 f4;
       float f;
    };
};

Data getData(Setting type);
Data getData(Setting type, gr::Float4 f4);
Data getData(Setting type, float f);

typedef std::list<Data> DataSequence;
typedef std::function<void(DataSequence&)> ApplyFunction;

/** Remove instance of d from sequence */
void remove(DataSequence& s, const Data& d);
/** Add instance of d to sequence. Replace duplicates, if exists. */
void add(DataSequence& s, Data& d);

/* Constructors. */

inline Data clearColorBuffer()
{
    return getData(CLEAR_COLOR_BUFFER);
}

inline Data clearDepthBuffer()
{
    return getData(CLEAR_DEPTH_BUFFER);
}

inline Data setClearColor(float r, float g, float b)
{
    return getData(SET_CLEAR_COLOR, gr::float4(r, g, b, 1.0f));
}

ApplyFunction getApply(ShaderDialect dialect);
std::string toString(DataSequence& data);


} // namespace state
} // namespace gu
